#include <51func.h>
typedef struct node_s {
    int num;
    struct node_s * pNext;
} node_t;
typedef struct queue_s {
    node_t *pFront;
    node_t *pRear;
    int queueSize;
} queue_t;
typedef struct shareRes_s {
    // queue_t *pqueue; // 定义shareRes 实际上了申请了一个指针
    queue_t queue; // 定义shareRes 实际上了申请了一个queue
    pthread_mutex_t mutex;
    pthread_cond_t cond;
} shareRes_t;
int enQueue(queue_t *pqueue,int num){
    node_t * pNew = (node_t *)calloc(1,sizeof(node_t));
    pNew->num = num;
    if(pqueue->queueSize == 0){
        pqueue->pFront = pNew;
        pqueue->pRear = pNew;
    }
    else{
        pqueue->pRear->pNext = pNew;
        pqueue->pRear = pNew;
    }
    ++pqueue->queueSize;
    return 0;
}
int deQueue(queue_t *pqueue){
    node_t *pCur = pqueue->pFront;
    pqueue->pFront = pCur->pNext;
    free(pCur);
    if(pqueue->pFront == NULL){
        pqueue->pRear = NULL;
    }
    --pqueue->queueSize;
    return 0;
}
int visitQueue(queue_t *pqueue){
    node_t * pCur = pqueue->pFront;
    while(pCur){
        printf("%4d", pCur->num);
        pCur = pCur->pNext;
    }
    printf("\n");
    return 0;
}
void *producer(void *arg){
    shareRes_t * pshareRes = (shareRes_t *)arg;
    while(1){
        pthread_mutex_lock(&pshareRes->mutex);
        while(pshareRes->queue.queueSize >= 10){
            pthread_cond_wait(&pshareRes->cond,&pshareRes->mutex);
        }
        // 入队操作是需要带锁运行的
        int num = rand()%1000;
        printf("-----------------\n");
        printf("before produce, size = %d ", pshareRes->queue.queueSize);
        visitQueue(&pshareRes->queue);
        enQueue(&pshareRes->queue,num);
        printf("after produce, num = %d ", num);
        visitQueue(&pshareRes->queue);
        pthread_cond_broadcast(&pshareRes->cond);
        pthread_mutex_unlock(&pshareRes->mutex);
        sleep(3); // sleep要在unlock之后
    }
}
void *consumer(void *arg){
    shareRes_t * pshareRes = (shareRes_t *)arg;
    sleep(5);
    while(1){
        pthread_mutex_lock(&pshareRes->mutex);
        while(pshareRes->queue.queueSize <= 0){
            pthread_cond_wait(&pshareRes->cond,&pshareRes->mutex);
        }
        printf("-------------------\n");
        printf("before consume, size = %d ", pshareRes->queue.queueSize);
        visitQueue(&pshareRes->queue);
        int front = pshareRes->queue.pFront->num;
        deQueue(&pshareRes->queue);
        printf("after consume, front = %d ", front);
        visitQueue(&pshareRes->queue);
        pthread_cond_broadcast(&pshareRes->cond);
        pthread_mutex_unlock(&pshareRes->mutex);
        sleep(1);
    }

}
//int main(int argc, char *argv[])
//{
//    queue_t queue;
//    memset(&queue,0,sizeof(queue));
//    int num;
//    for(int i = 0; i < 8; ++i){
//        num = rand()%1000;
//        printf("num = %d\n", num);
//        enQueue(&queue,num);
//        visitQueue(&queue);
//        printf("-------------------\n");
//    }
//    
//    for(int i = 0; i < 8; ++i){
//        printf("front = %d\n", queue.pFront->num);
//        deQueue(&queue);
//        visitQueue(&queue);
//        printf("----------------------\n");
//    }
//    return 0;
//
//}
int main(){
    // 初始化 队列、锁、条件变量
    shareRes_t shareRes;
    memset(&shareRes.queue,0,sizeof(queue_t));
    pthread_mutex_init(&shareRes.mutex,NULL);
    pthread_cond_init(&shareRes.cond,NULL);

    // 准备一开始的商品
    int num;
    for(int i = 0; i < 8; ++i){
        num = rand()%1000;
        printf("num = %d\n", num);
        enQueue(&shareRes.queue,num);
        visitQueue(&shareRes.queue);
        printf("-------------------\n");
    }
    
    // 启动生产者和消费者
    pthread_t tid1,tid2,tid3,tid4,tid5;
    pthread_create(&tid1,NULL,producer,&shareRes);
    pthread_create(&tid2,NULL,producer,&shareRes);
    pthread_create(&tid3,NULL,producer,&shareRes);
    pthread_create(&tid4,NULL,consumer,&shareRes);
    pthread_create(&tid5,NULL,consumer,&shareRes);
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    pthread_join(tid3,NULL);
    pthread_join(tid4,NULL);
    pthread_join(tid5,NULL);
}

